﻿using System;
using System.Collections.Generic;
using UnityEngine;
using VoxelBlock;using Vector3Int = VoxelBlock.Vector3Int;
using VoxelBlock.VoxelBlock3D;
using VoxelBlock.VoxelInput;

public class VoxelEditorMastermind : MonoBehaviour
{

    public static VoxelEditorMastermind instance;

    /// <summary>
    /// Main Voxel
    /// </summary>
    [SerializeField]
    [HeaderAttribute("Main Voxel"), Space(-5)]
    public GameObject mainVoxel;


    /// <summary>
    /// 存档读写
    /// </summary>
    [SerializeField]
    [HeaderAttribute("存档读写"), Space(-5)]
    SaveReadWrite saveReadWrite;

    /// <summary>
    /// 一片操作时候的碰撞体
    /// </summary>
    [SerializeField]
    [HeaderAttribute("一片操作时候的碰撞体"), Space(-5)]
    GameObject meshSliceCollider;

    /// <summary>
    /// 镜头的Y节点
    /// </summary>
    [SerializeField]
    [HeaderAttribute("镜头的Y节点"), Space(-5)]
    Transform mainCameraY;

    /// <summary>
    /// 通过相机确定绘制点的坐标，相当于手
    /// </summary>
    MoveBrushComponent moveBrushComponent;

    /// <summary>
    /// 绘制操作核心
    /// </summary>
    OperateCreate3D operateCreate3D;

    /// <summary>
    /// 网格图片
    /// </summary>
    [SerializeField]
    [HeaderAttribute("网格图片"), Space(-5)]
    Texture2D gridTexture;

    /// <summary>
    /// 编辑摄像头
    /// </summary>
    [SerializeField]
    [HeaderAttribute("编辑摄像头"), Space(-5)]
    Camera newEditorSelectCamera;





    [SerializeField]
    public Material mainMaterial;

    [SerializeField]
    UIItemTransformUnitComponent mainUIItemTransformUnitComponent;

    VoxelCategories.OperationSelectOperator selectOperator;
    public VoxelCategories.OperationSelectOperator SelectOperator
    {
        get
        {
            return selectOperator;
        }

        set
        {
            selectOperator = value;
        }
    }

    VoxelCategories.OperationBehavior behavior;
    public  VoxelCategories.OperationBehavior Behavior
    {
        get
        {
            return behavior;
        }

        set
        {
            behavior = value;
            if (value == VoxelCategories.OperationBehavior.Transform)
            {
                TransformVector.Thas.node.SetActive(true);
            }
            else
            {
                TransformVector.Thas.node.SetActive(false);
            }
        }
    }

    VoxelCategories.OperationBrush select;
    public  VoxelCategories.OperationBrush Select
    {
        get
        {
            return select;
        }

        set
        {
            select = value;
        }
    }

    private Texture2D editingTex;

    /// <summary>
    /// 导入进来的材质包
    /// </summary>
    public Texture2D userTexture;

    /// <summary>
    /// 当前颜色包
    /// </summary>
    public Texture2D EditingTex
    {
        get
        {
            if (editingTex == null)
            {
                editingTex = Resources.Load<Texture2D>("Texture/Pal1");
            }
            return editingTex;
        }

        set
        {
            mainMaterial.mainTexture = value;
            editingTex = value;
        }
    }


    public Action<int> OnSelectUVKey = null;
    public int nowSelectUVKey;
    public void SetNowSelectUVKey(int selectUVKey)
    {
        nowSelectUVKey = selectUVKey;
        if (OnSelectUVKey != null)
        {
            OnSelectUVKey(selectUVKey);
        }
    }

    public Vector2Int nowSelectUV;

    private Vector3Int selectPosition;
    public Vector3Int NowSelectPosition
    {
        get
        {
            return selectPosition;
        }
    }


    //public override bool IsDrawOver
    //{
    //    get
    //    {
    //        return is2DEditor;
    //    }
    //}

    public VoxelDirection brushDirection;

    private VoxelDirection GetBrushDirection()
    {
        return brushDirection;
    }
    private VoxelCategories.OperationBrush GetSelect()
    {
        return select;
    }
    private VoxelCategories.OperationBehavior GetBehavior()
    {
        return behavior;
    }
    private VoxelCategories.OperationSelectOperator GetSelectOperator()
    {
        return selectOperator;
    }

    /// <summary>
    /// 填充参数
    /// </summary>
    OperationImplement.StartSliceArg startSliceArg = new OperationImplement.StartSliceArg();
    public OperationImplement.StartSliceArg StartSliceArg
    {
        get
        {
            return startSliceArg;
        }
    }
    //public void UISliceArgGet(GameObject trueColor, GameObject trueFill)
    //{
    //    startSliceArg.getColor = !startSliceArg.getColor;
    //    if (startSliceArg.getColor)
    //    {
    //        trueColor.SetActive(true);
    //        trueFill.SetActive(false);
    //    }
    //    else
    //    {
    //        trueColor.SetActive(false);
    //        trueFill.SetActive(true);
    //    }
    //}
    //public void UISliceArgSet(GameObject trueColor, GameObject trueFill)
    //{
    //    startSliceArg.setColor = !startSliceArg.setColor;
    //    if (startSliceArg.setColor)
    //    {
    //        trueColor.SetActive(true);
    //        trueFill.SetActive(false);
    //    }
    //    else
    //    {
    //        trueColor.SetActive(false);
    //        trueFill.SetActive(true);
    //    }
    //}
    //public void UISliceArgIs8(GameObject trueIs8, GameObject trueIs4)
    //{
    //    startSliceArg.is8 = !startSliceArg.is8;
    //    if (startSliceArg.is8)
    //    {
    //        trueIs8.SetActive(true);
    //        trueIs4.SetActive(false);
    //    }
    //    else
    //    {
    //        trueIs8.SetActive(false);
    //        trueIs4.SetActive(true);
    //    }
    //}



    void Awake()
    {
        instance = this;

        moveBrushComponent = GetComponent<MoveBrushComponent>();

        operateCreate3D = new OperateCreate3D(mainVoxel, meshSliceCollider, mainCameraY, mainMaterial,
            GetBrushDirection, GetBehavior, GetSelect, GetSelectOperator, SetNowSelectUVKey, mainUIItemTransformUnitComponent);
        operateCreate3D.Show();

        mainMaterial.SetTexture("_UV3Tex", VoxelMetadata3D.Instance.shadows);
    }

    void Start()
    {
        //var colors = operateCreate3D.InputSlabVoxel(@"C:\Users\Administrator\Desktop\AK47.vox");
        //EditingTex.SetPixels32(colors);
        //EditingTex.Apply();

        //if (UIComponentMastermind.instance.m_ColorPalatteComponent)
        //{
        //    UIComponentMastermind.instance.m_ColorPalatteComponent.OpenTextureIndexU();
        //}
        SetGrid(UserData.Thas.IsGrid);
        StartSliceArg.Is8 = UserData.Thas.Is8_StartSliceArg;
        StartSliceArg.GetColor = UserData.Thas.GetColor_StartSliceArg;
        StartSliceArg.SetColor = UserData.Thas.SetColor_StartSliceArg;

}

void Update()
    {
        moveBrushComponent.UpdateBrush();
        if (Input.GetMouseButtonDown(0))
        {
            if (isRun) 
            {
                operateCreate3D.OperationOver(NowSelectPosition, nowSelectUVKey, false);//停止
            }
            else
            {
                isEditor = moveBrushComponent.UpdateBrush();
                if (isEditor)
                {
                    selectPosition = moveBrushComponent.selectBrushTransform.position;

                    operateCreate3D.OperationStart(NowSelectPosition, nowSelectUVKey);
                    isRun = true;
                }
            }
        }
         if (Input.GetMouseButton(0))
        {
            if (isRun)
            {
                isEditor = moveBrushComponent.UpdateBrush();
                selectPosition = moveBrushComponent.selectBrushTransform.position;
                if (isEditor)
                {
                    operateCreate3D.OperationRun(NowSelectPosition, nowSelectUVKey);
                }
                else
                {
                    //operateCreate3D.OperationStop(NowSelectPosition, nowSelectUVKey);
                    operateCreate3D.OperationOver(NowSelectPosition, nowSelectUVKey, true);//暂停
                }
            }
        }
        else//没有按住
        {
            if (isRun)
            {
                isEditor = moveBrushComponent.UpdateBrush();
                selectPosition = moveBrushComponent.selectBrushTransform.position;
                operateCreate3D.OperationOver(NowSelectPosition, nowSelectUVKey, false);//停止
                isRun = false;
            }
        }


#if UNITY_EDITOR
        if (Input.GetKeyDown(KeyCode.Z))
#else   
        if (Input.GetKeyDown(KeyCode.Z) && Input.GetKey(KeyCode.LeftControl))
#endif
        {
            operateCreate3D.Revoke();
        }

#if UNITY_EDITOR
        if (Input.GetKeyDown(KeyCode.Y))
#else
        if (Input.GetKeyDown(KeyCode.Y) && Input.GetKey(KeyCode.LeftControl))
#endif
        {
            operateCreate3D.BackRevoke();
        }

        if (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt))
        {
            if (onClickRead)
            {

            }
            else
            {
                if (isRun)
                {
                    //isEditor = moveBrushComponent.UpdateBrush();
                    //selectPosition = moveBrushComponent.selectBrushTransform.position;
                    //operateCreate3D.OperationOver(NowSelectPosition, nowSelectUVKey, false);//停止
                    //isRun = false;
                }
                else
                {
                    backBehavior = behavior;
                    behavior = VoxelCategories.OperationBehavior.Read;
                    operateCreate3D.OperationStart(NowSelectPosition, nowSelectUVKey);
                    onClickRead = true;
                }
            }
        }
        else
        {
            if (onClickRead)
            {
                behavior = backBehavior;
                operateCreate3D.OperationStart(NowSelectPosition, nowSelectUVKey);
                onClickRead = false;
            }
        }

        if (Input.GetKeyDown(KeyCode.D) && Input.GetKey(KeyCode.LeftControl))
        {
            ClearSelect();
        }
    }

    bool onClickRead = false;
    VoxelCategories.OperationBehavior backBehavior;

    bool isRun = false;
    bool isEditor = false;

    public Vector3Int[] TestAdd(IEnumerable<Voxel3D> allp)
    {
       return operateCreate3D.TestAdd(allp);
    }
    public void TestRemove(IEnumerable<Vector3Int> allp)
    {
        operateCreate3D.TestRemove(allp);
    }
    public Voxel3D TestRead(Vector3Int p)
    {
        return operateCreate3D.TestRead(p);
    }
    
    //Vector3Int startPosition;
    //public void DragOver(bool isStop)
    //{
    //    if (isStop)
    //    {
    //        operateCreate3D.OperationOver(NowSelectPosition, nowSelectUVKey, isStop);
    //    }
    //    else
    //    {
    //        moveBrushComponent.UpdateBrush();
    //        selectPosition = moveBrushComponent.selectBrushTransform.position;
    //    }
    //    isRun = false;
    //}

    //public void DragRun()
    //{
    //    if (isRun)
    //    {
    //        //moveBrushComponent.UpdateBrush();
    //        //selectPosition = moveBrushComponent.selectBrushTransform.position;

    //        //Vector3 cursorPos = Input.mousePosition;
    //        //Ray ray = uiCamera.ScreenPointToRay(cursorPos);
    //        //RaycastHit objhit;
    //        if (Physics.Raycast(ray, out objhit, 100, uiLayerMask))
    //        {
    //            operateCreate3D.OperationStop(NowSelectPosition, nowSelectUVKey);
    //        }
    //        else
    //        {
    //            operateCreate3D.OperationRun(NowSelectPosition, nowSelectUVKey);
    //        }
    //    }
    //}

    //public void DragStart()
    //{
    //    operateCreate3D.OperationStart(NowSelectPosition, nowSelectUVKey);
    //}

    public void DeleteSave(string fileName)
    {
        operateCreate3D.DeleteSave(fileName, saveReadWrite);
    }

    public void ReadSave(string fileName)
    {
        operateCreate3D.ClearAll();
        ProxyOperation[] proxyOperations;
        var riovox = saveReadWrite.Read(fileName, out  proxyOperations, EditingTex);//operateCreate3D.nowProxyOperation
        ReadRiovox(riovox, proxyOperations);
        //EditingTex = userTexture;
    }

    public void WriteSave(string fileName)
    {
        ProxyOperation[] allOverProxyOperation;
        RioVoxelData riovox = SaveRiovox.GetRiovox(out allOverProxyOperation);
        operateCreate3D.WriteSave(fileName, saveReadWrite, EditingTex, riovox, allOverProxyOperation);
    }

    public void ReadPrefab(string fileName)
    {
        operateCreate3D.ReadPrefab(fileName, saveReadWrite);
    }
    


    public void SelectOperationBehaviorAdd()
    {
        this.Behavior = VoxelCategories.OperationBehavior.Add;
    }
    public void SelectOperationBehaviorRemove()
    {
        this.Behavior = VoxelCategories.OperationBehavior.Remove;
    }
    public void SelectOperationBehaviorPaint()
    {
        this.Behavior = VoxelCategories.OperationBehavior.Paint;
    }
    public void SelectOperationBehaviorRead()
    {
        this.Behavior = VoxelCategories.OperationBehavior.Read;
    }
    public void SelectOperationBehaviorSelect()
    {
        this.Behavior = VoxelCategories.OperationBehavior.Select;
    }
    public void SelectOperationBehaviorTransform()
    {
        this.Behavior = VoxelCategories.OperationBehavior.Transform;
    }

    public void SetOperationSelect(VoxelCategories.OperationBrush select)
    {
        this.Select = select;
    }
    public void SetOperationSelect(int select)
    {
        VoxelCategories.OperationBrush os = (VoxelCategories.OperationBrush)select;
        this.Select = os;
    }

    public void SelectOperationSelecteBrush()
    {
        this.Select = VoxelCategories.OperationBrush.Brush;
    }
    public void SelectOperationSelecteRectangle()
    {
        this.Select = VoxelCategories.OperationBrush.Rectangle;
    }
    public void SelectOperationSelecteSlice()
    {
        this.Select = VoxelCategories.OperationBrush.Slice;
    }
    public void SelectOperationSelecteLine()
    {
        this.Select = VoxelCategories.OperationBrush.Line;
    }
    public void SelectOperationSelecteScale()
    {
        this.Select = VoxelCategories.OperationBrush.Scale;
    }

    public void SetSelectOperatorUnion()
    {
        this.SelectOperator = VoxelCategories.OperationSelectOperator.Union;
    }
    public void SetSelectOperatorRemove()
    {
        this.SelectOperator = VoxelCategories.OperationSelectOperator.Remove;
    }

    //public void SetSelectOperatorIntersection()
    //{
    //    this.SelectOperator = VoxelCategories.OperationSelectOperator.Intersection;
    //}

    

    public void ClearAll()
    {
        operateCreate3D.ClearAll();
    }

    public void ClearSelect()
    {
        operateCreate3D.ClearSelect();
    }





    public void Revoke()
    {
        operateCreate3D.Revoke();
    }

    public void BackRevoke()
    {
        operateCreate3D.BackRevoke();
    }


    public void Separate()
    {
        operateCreate3D.Separate();
    }

    public void ReadRiovox(RioVoxelData riovox, ProxyOperation[] proxyOperations)
    {
        VoxelUnitData[] allVoxel = riovox.allVoxel;
        for (int i = 0; i < allVoxel.Length; i++)
        {
            VoxelUnitData data = allVoxel[i];

            ProxyOperation proxyOperation;
            if (proxyOperations == null)
            {
                proxyOperation = null;
            }
            else
            {
                proxyOperation = proxyOperations[i];
            }
            List<Voxel3D> voxel3ds = new List<Voxel3D>();

            Vector3Int min = data.min;
            int sizeX = data.size.x;
            int sizeY = data.size.y;
            int sizeZ = data.size.z;
            var bytes = data.voxelData;
            for (int x = 0 , id = 0; x < sizeX; x++)
            {
                for (int y = 0; y < sizeY; y++)
                {
                    for (int z = 0; z < sizeZ; z++, id++)
                    {
                        if (bytes[id] != 255)
                        {
                            voxel3ds.Add(new Voxel3D(new Vector3Int(x + min.x, y + min.y, z + min.z), bytes[id]));
                        }
                    }
                }
            }
            if (riovox.transforms.Length > i)
            {
                VoxelBoneTransform transform = riovox.transforms[i];
                operateCreate3D.AddPart(transform.name, voxel3ds, data.zero, data.world, min, true, transform.localPosition, proxyOperation);
            }
            else
            {
                operateCreate3D.AddPart(data.name, voxel3ds, data.zero, data.world, min, false, new Vector3(0, 0, 0), proxyOperation);
            }
        }
        operateCreate3D.NowEditorMain();
    }


    public DrawVoxel3DCoreManager.DrawVoxel3DCoreValue GetDrawVoxel3DCoreValue(DrawVoxel3DCore core)
    {
       return operateCreate3D.drawVoxel3DCoreManager.allCore[core];
    }

    

    public void SaveMainVoxel(string path)
    {
        VoxelInputInfo itemVoxelInputInfo = operateCreate3D.GetFileVoxelMainData();
        VoxelInput.SetVoxelData(itemVoxelInputInfo, path);
    }

    public Color32[] InputSlabVoxel(string path)
    {
        return operateCreate3D.InputSlabVoxel(path);
    }

    public SimpleVoxel[] AddVoxels(IEnumerable<Voxel3D> voxs)
    {
        return operateCreate3D.nowDrawVoxel3DCore.DrawAddBlock(voxs);
    }
    public List<SimpleVoxel> DrawRemoveBlock(IEnumerable<SimpleVoxel> voxs)
    {
        List<Vector3Int> list = new List<Vector3Int>();
        foreach (var item in voxs)
        {
            list.Add(item.position);
        }
        return operateCreate3D.nowDrawVoxel3DCore.DrawRemoveBlock(list);
    }


    public void HideNowDrawVoxel3DCore()
    {
        operateCreate3D.nowDrawVoxel3DCore.RootTransform.gameObject.SetActive(false);
    }

    public void SetGrid(bool isShow)
    {
        if (isShow)
        {
            foreach (var item in operateCreate3D.drawVoxel3DCoreManager.allCore)
            {
                item.Key.mainMaterial.SetTexture("_GridTex", gridTexture);
            }
        }
        else
        {
            foreach (var item in operateCreate3D.drawVoxel3DCoreManager.allCore)
            {
                item.Key.mainMaterial.SetTexture("_GridTex", null);
            }
        }
    }

}
